using System;
using System.Collections.Generic;
using System.Text;
using BoOnce.Xml;
using BoOnce.Components;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using BoOnce.GameLogic.Entities;
using BoOnce.GameLogic.Entities.Drawable.Scenery;
using BoOnce.Steps;
using BoOnce.Helpers;
using BoOnce.Core.Components;
using BoOnce.Core.Helpers;
using BoOnce.Core;

namespace BoOnce.GameLogic
{
    class Level : Step
    {
        #region Constantes
        const String LEVEL_DESCRIPTOR_NAME = "level.info";
        #endregion

        #region Private Attributes
        PhysicComponentConfigXml _PhysicComponentConfig;
        PhysicComponent _PhysicComponent;
        List<Background> _Backgrounds;
        List<PhysicalScenery> _PhysicalSceneries;
        List<Player> _Players;
        Game _Game;
        LevelXml _LevelXml;
        InputComponent _Input;
        #endregion

        #region Properties
        public PhysicComponentConfigXml PhysicComponentConfig
        {
            get { return _PhysicComponentConfig; }
        }

        public List<Background> Backgrounds
        {
            get { return _Backgrounds; }
        }

        public List<PhysicalScenery> PhysicalSceneries
        {
            get
            {
                return _PhysicalSceneries;
            }
        }

        public List<Player> Players { get { return _Players; } }

        public PhysicComponent PhysicComponent
        {
            get
            {
                return _PhysicComponent;
            }
        }
        #endregion

        public Level(Game game, String name)
            : base(game, "Level:" + name )
        {
            _Game = game;
            _Backgrounds = new List<Background>();
            _PhysicalSceneries = new List<PhysicalScenery>();
            _Players = new List<Player>();
            _Input = (InputComponent)game.Services.GetService(typeof(InputComponent));
            _LevelXml = (LevelXml)XmlStorage.Load(Settings.CONTENT_ROOT_PATH + "/" + Settings.CONTENT_LEVEL_PATH + "/" + name + "/" + LEVEL_DESCRIPTOR_NAME, typeof(LevelXml));

            #region Init Physics Engine
            // Load value for Physical Engine
            _PhysicComponentConfig = _LevelXml.PhysicEngine;
            _PhysicComponent = new PhysicComponent(game, _PhysicComponentConfig);
            _PhysicComponent.Enabled = true;
            _PhysicComponent.UpdateOrder = Priority.PHYSIC_COMPONENT;
            #endregion

            // Start Physic component
            _Game.Components.Add(_PhysicComponent);
        }

        #region Step
        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
        }

        public override void LoadContent()
        {
            SceneryXml sceneryXml = _LevelXml.Scenery;
            #region Load Backgrounds
            foreach (BackgroundSceneryXml b in sceneryXml.Backgrounds)
            {
                Texture2D backgroundTexture = _Game.Content.Load<Texture2D>(Settings.CONTENT_BACKGROUND_SCENERY_PATH + "/" + b.Name);
                Background background = new Background(backgroundTexture, b.Type, b.SlideCoeff);
                background.DrawedOrder = b.DrawOrder;
                _Backgrounds.Add(background);
            }
            #endregion

            #region Load PhysicalSceneries
            foreach (PhysicalSceneryXml p in sceneryXml.PhysicalSceneries)
            {
                switch (p.Type)
                {
                    case PhysicalSceneryType.STREETLAMP:
                        Texture2D streetlampTexture = _Game.Content.Load<Texture2D>(Settings.CONTENT_SCENERY_PATH + "/" + p.ContentName);
                        Streetlamp streetlamp = new Streetlamp(streetlampTexture, p.Position, p.Width, p.Height, p.Mass);
                        _PhysicalSceneries.Add(streetlamp);
                        break;

                    default:
                        Logger.WriteError(this, "Impossible to load PhysicalSceneryType:" + p.Type);
                        break;
                }
            }
            #endregion

            #region Load Players
            foreach (PlayerXml player in _LevelXml.Players)
            {
                _Players.Add(new BusPlayer(player.PlayerIndex,player.Position,player.Name,player.Height,player.Width,player.Mass));
            }
            #endregion
            base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
            // Display Backgrounds
            foreach (Background bg in _Backgrounds)
            {
                bg.Update(gameTime);
                bg.DEC.Add(bg);
            }

            // Display plysical sceneries
            foreach (PhysicalScenery ps in _PhysicalSceneries)
            {
                ps.Update(gameTime);
                ps.DrawedOrder = 100;
                ps.DEC.Add(ps);
            }

            //_Hero.DrawedOrder = 1000;
            //_Hero.DEC.Add(_Hero);

            if (_Input.IsNewPress(PlayerIndex.One, InputComponent.Buttons.Action2))
            {
                Logger.WriteInfo("impulse");
                //_Hero.Body.ApplyImpulse(new Vector2(0f,-100.0f));
                //_Hero.Body.ApplyForce(new Vector2(0f, -15100.0f));
                //_Hero.Body.LinearDragCoefficient = 0.02f;
                //_Hero.Body.RotationalDragCoefficient = 0.02f;
            }

            foreach (Player player in _Players)
            {
                player.Update(gameTime);
                player.DrawedOrder = 100;
                player.DEC.Add(player);
            }
            base.Update(gameTime);
        }

        public override void UnloadContent()
        {
            // TODO
            base.UnloadContent();
        }
        #endregion

    }
}
